﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;

namespace Maxleaf.EDI.Infrastructure
{
    public class ServiceProxy<TInterface> : ClientBase<TInterface>, IDisposable where TInterface : class
    {
        public delegate void ServiceProxyDelegate<T>(TInterface proxy);

        public ServiceProxy()
            : base(typeof(TInterface).ToString())
        {
        }

        public ServiceProxy(string endpointConfigurationName)
            : base(endpointConfigurationName)
        {
        }

        public ServiceProxy(string endpointConfigurationName, string endpointAddress)
            : base(endpointConfigurationName, endpointAddress)
        {
        }

        public TInterface Proxy
        {
            get
            {
                return this.Channel;
            }
        }

        public static void Call(ServiceProxyDelegate<TInterface> proxyDelegate)
        {
            Call(proxyDelegate, typeof(TInterface).ToString());
        }

        public static void Call(ServiceProxyDelegate<TInterface> proxyDelegate, string endpointConfigurationName)
        {
            ChannelFactory<TInterface> channel = new ChannelFactory<TInterface>(endpointConfigurationName);

            try
            {
                proxyDelegate(channel.CreateChannel());
            }
            catch (Exception exp)
            {
                throw exp;
            }
            finally
            {
                if (channel.State == CommunicationState.Faulted)
                {
                    channel.Abort();
                }
                else
                {
                    try
                    {
                        channel.Close();
                    }
                    catch
                    {
                        channel.Abort();
                    }
                }
            }
        }

        public void Dispose()
        {
            if (this.State == CommunicationState.Faulted)
            {
                this.Abort();
            }
            else
            {
                try
                {
                    this.Close();
                }
                catch
                {
                    this.Abort();
                }
            }
        }

        protected override TInterface CreateChannel()
        {
            var facotry = new ChannelFactory<TInterface>(this.Endpoint);

            foreach (var op in facotry.Endpoint.Contract.Operations)
            {
                var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();

                if (dataContractBehavior != null)
                {
                    dataContractBehavior.MaxItemsInObjectGraph = 2147483647;
                }
            }

            ////var binding = facotry.Endpoint.Binding as BasicHttpBinding;

            ////binding.MaxBufferPoolSize = 2147483647;
            ////binding.MaxBufferSize = 2147483647;
            ////binding.MaxReceivedMessageSize = 2147483647;
            ////binding.ReaderQuotas.MaxArrayLength = 2147483647;
            ////binding.ReaderQuotas.MaxBytesPerRead = 2147483647;
            ////binding.ReaderQuotas.MaxDepth = 2147483647;
            ////binding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
            ////binding.ReaderQuotas.MaxStringContentLength = 2147483647;
            return facotry.CreateChannel();
        }
    }
}
